
#ifndef __utility_functions_vararg_method__
#define __utility_functions_vararg_method__

#include "quickjs/env.h"
#include "quickjs/quickjs.h"
#include "register/utility_functions/register_utility_functions.h"
#include "register/utility_functions/utility_functions_vararg_method.hpp"
#include "utils/func_utils.hpp"
#include "utils/quickjs_helper.hpp"
#include "utils/str_helper.hpp"
#include <godot_cpp/variant/builtin_types.hpp>
#include <godot_cpp/variant/utility_functions.hpp>

using namespace godot;

{%- macro return_type(ret) -%}
	{%- if ret -%}
{{ret}}
	{%- else -%}
void
	{%- endif -%}
{%- endmacro %}

{%- set vararg_methods = utility_functions | selectattr('is_vararg', 'equalto', true) | list -%}

{%- for method in vararg_methods %}
{{return_type(method['return_type'])}} js_{{method['name']}}_internal(const Variant **p_args, GDExtensionInt p_arg_count) {
	static GDExtensionPtrUtilityFunction _gde_function = internal::gdextension_interface_variant_get_ptr_utility_function(StringName("{{method['name']}}")._native_ptr(), {{method['hash']}});
	CHECK_METHOD_BIND(_gde_function);
	Variant ret;
	_gde_function(&ret, reinterpret_cast<GDExtensionConstVariantPtr *>(p_args), p_arg_count);
	{%- if method['return_type'] %}
	return ret;
	{%- endif %}
}
{%- endfor %}

{%- for method in vararg_methods %}
{{return_type(method['return_type'])}} js_{{method['name']}}({{connect_mutable_args(method['arguments'])}}) {
	std::vector<Variant> variant_args;
	std::vector<Variant *> variant_args_ptr;
	{%- for arg in method['arguments'] %}
	variant_args.push_back(p_{{arg['name']}});
	{%- endfor %}
		for (int i = 0; i < p_args.size(); i++) {
		variant_args.push_back(p_args[i]);
	}	
	for (int i = 0; i < variant_args.size(); i++) {
		variant_args_ptr.push_back(&variant_args[i]);
	}
	js_{{method['name']}}_internal(const_cast<const Variant **>(variant_args_ptr.data()), variant_args_ptr.size());
}
{%- endfor %}

#endif // __utility_functions_vararg_method__